package com.caiying.dota.net;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;

public class HttpConnector {
	private static final int CONNECTIONTIMEOUT = 5000;
	private static final int SOTIMEOUT = 5000;
	private static HttpClient httpClient = null;
	
	public static HttpClient getHttpClient(){
		if(httpClient == null){
			HttpParams params = new BasicHttpParams();
			
			HttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, CONNECTIONTIMEOUT);
			HttpConnectionParams.setSoTimeout(httpParameters, SOTIMEOUT);
	        ConnManagerParams.setMaxTotalConnections(params, 100);
	        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
	        // Create and initialize scheme registry 
	        SchemeRegistry schemeRegistry = new SchemeRegistry();
	        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
	        // Create an HttpClient with the ThreadSafeClientConnManager.
	        // This connection manager must be used if more than one thread will
	        // be using the HttpClient.
	        ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
	        httpClient = new DefaultHttpClient(cm, params);
		}
        return httpClient;
	}
	
	
	
	public static InputStream getInputStream(String url) {
		HttpGet get = new HttpGet(url);
		InputStream is = null;
		try {
			HttpResponse resp = getHttpClient().execute(get);
			HttpEntity entity = resp.getEntity();
			if(entity != null) {
				is = entity.getContent();
//				Logger.verbose("request url : " + url);
			}
		} catch (Exception e) {
			get.abort();
//			Logger.error("request url : " + url + " exception:" + e.getMessage(), e);
		}
		return is;
	}
	
	public static String converStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
	
	public static byte[] getBytes(String url) {
		HttpGet get = new HttpGet(url);
		byte[] bytes = null;
		try {
			HttpResponse resp = getHttpClient().execute(get);
			HttpEntity entity = resp.getEntity();
			if(entity != null) {
				bytes = EntityUtils.toByteArray(entity);
//				Logger.verbose("request url : " + url);
			}
		} catch (Exception e) {
			get.abort();
//			Logger.error("request url : " + url + " exception : " + e.getMessage(), e);
		}
		return bytes;
	}
	
	public static String getString(String url, String encoding) {
		byte[] result = getBytes(url);
		if(result != null) {
			try {
				return new String(result, encoding);
			} catch (UnsupportedEncodingException e) {
			}
		}
		return null;
	}
	
	public static String getString(String url) {
		return getString(url, "UTF-8");
	}
	
	
	/**
	 * @param url
	 * @param data
	 * @param isMultiPart
	 * @return
	 */
	public static String postMap(String url, Map<String, String> data) {
//		Logger.verbose(TAG, "postData url=" + url + " data=" + data);
		HttpPost post = new HttpPost(url);
		HttpEntity entity = null;
		try {
			entity = createEntity(data);
		} catch (UnsupportedEncodingException e) {
//			Logger.error("UnsupportedEncodingException", e);
		}
		if(entity == null) {
			return null;
		}
		post.setEntity(entity);
		HttpResponse resp = null;
		try {
			resp = getHttpClient().execute(post);
//			Logger.verbose(TAG, "getStatusLine=" + resp.getStatusLine().toString());
			if(resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String response = EntityUtils.toString(resp.getEntity(), "UTF-8");
//				Logger.verbose(TAG, "response:" + response);
				return response;
			}
		} catch (ClientProtocolException e) {
//			Logger.error("ClientProtocolException", e);
		} catch (IOException e) {
//			Logger.error("IOException", e);
		}
		return null;
	}
	
	
	public static String postMap(String url, Map<String, Object> data, boolean isMultiPart) {
//		Logger.verbose(TAG, "上传数据 url=" + url + " data=" + data);
		HttpPost post = new HttpPost(url);
		HttpEntity entity = null;
		try {
			entity = createEntity(data, isMultiPart);
		} catch (UnsupportedEncodingException e) {
//			Logger.error("UnsupportedEncodingException", e);
		}
		if(entity == null) {
			return null;
		}
		post.setEntity(entity);
		HttpResponse resp = null;
		try {
			resp = getHttpClient().execute(post);
			if(resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String response = EntityUtils.toString(resp.getEntity(), "UTF-8");
//				Logger.verbose(TAG, "response:" + response);
				return response;
			}
		} catch (ClientProtocolException e) {
//			Logger.error("ClientProtocolException", e);
		} catch (IOException e) {
//			Logger.error( "IOException", e);
		}
		return null;
	}
	
	/**
	 * @param data
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static HttpEntity createEntity (Map<String, String> data) throws UnsupportedEncodingException {
		ArrayList<NameValuePair> fields = new ArrayList<NameValuePair>();
		for(String key: data.keySet()) {
			fields.add(new BasicNameValuePair(key, String.valueOf(data.get(key))));
		}
		return new UrlEncodedFormEntity(fields, "UTF-8");
	}
	
	public static HttpEntity createEntity (Map<String, Object> data, boolean isMultiPart) throws UnsupportedEncodingException {
		HttpEntity result = null;
		if(isMultiPart) {
			MultipartEntity entity = new MultipartEntity();
			for(String key: data.keySet()) {
				Object obj = data.get(key);
				if(obj == null) {
					continue;
				}
				if(obj instanceof File) {
					File file = (File) obj;
					entity.addPart(key, new FileBody(file));
				} else if(obj instanceof byte[]) {
					byte[] fileContent = (byte[]) obj;
					entity.addPart(key, new ByteArrayBody(fileContent, "upload.jpg"));
				} else {
					entity.addPart(key, StringBody.create(String.valueOf(obj), "text/plain", Charset.forName("UTF-8")) );
				}
			}
			result = entity;
		} else {
			ArrayList<NameValuePair> fields = new ArrayList<NameValuePair>();
			for(String key: data.keySet()) {
				fields.add(new BasicNameValuePair(key, String.valueOf(data.get(key))));
			}
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(fields, "UTF-8");
			result = entity;
		}
		return result;
	}
	
	public static void shutdownHttpClient() {
		getHttpClient().getConnectionManager().shutdown();
	}
}
